#include "UMLCanvas.h"
#include "PaintVisitor.h"
#include "../model/UMLDiagram.h"
#include "../base/MouseListener.h"

#include <algorithm>
#include <QDebug>

UMLCanvas::UMLCanvas(UMLDiagram* diagram, QWidget* parent)
:	QWidget(parent),
	_diagram(diagram), _trans(10), _ml(NULL),
	_observer(*this) // safe, see DiagramObserver::DiagramObserver.
{
	setPalette(QPalette(Qt::white));   // set window color to white
	setAutoFillBackground(true);
	setMouseTracking(true);

	diagram->attach(&_observer);
}

UMLCanvas::~UMLCanvas()
{
	_diagram->unattach(&_observer);
}

QSize UMLCanvas::minimumSizeHint() const
{
	return QSize(400, 400);
}

QSize UMLCanvas::sizeHint() const
{
	using std::min;

	QSize dSize = _diagram->size();
	// Base it on diagram size, but only up to a reasonable maximum.
	return QSize(min(dSize.width(), 600), min(dSize.height(), 600));
}

UMLDiagram& UMLCanvas::diagram()
{
	return *_diagram;
}

const PointTranslator& UMLCanvas::trans() const
{
	return _trans;
}

const MouseListener* UMLCanvas::mouseListener() const
{
	return _ml;
}

void UMLCanvas::setMouseListener(MouseListener* ml)
{
	_ml = ml;
}

void UMLCanvas::clearSelection()
{
	_selected.clear();

	emit selectionChanged(NULL);

	update();
}

void UMLCanvas::select(UMLObject* obj)
{
	_selected.insert(obj);

	emit selectionChanged(obj);

	update();
}

void UMLCanvas::paintEvent(QPaintEvent*)
{
	QPainter painter(this);
	PaintVisitor v(_trans, painter, _selected, _ghosts);

	for (UMLDiagram::iterator iter = _diagram->begin();
			iter != _diagram->end(); ++iter)
		(*iter)->accept(v);
}

void UMLCanvas::mouseMoveEvent(QMouseEvent* ev)
{
	if (_ml)
		_ml->mouseMoveEvent(*ev);
}

void UMLCanvas::mousePressEvent(QMouseEvent* ev)
{
	qDebug() << "Mouse clicked at: " << ev->pos();

	if (_ml)
		_ml->mousePressEvent(*ev);
}

void UMLCanvas::mouseReleaseEvent(QMouseEvent* ev)
{
	if (_ml)
		_ml->mouseReleaseEvent(*ev);
}

UMLCanvas::DiagramObserver::DiagramObserver(UMLCanvas& canvas)
: _canvas(canvas)
{
}

void UMLCanvas::DiagramObserver::update(Observable*)
{
	_canvas.update();
}

